﻿
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;

namespace MinGuiLuo.PluginSystem
{
    /// <summary>
    /// Library Module Plugins
    /// </summary>
    public partial class PluginSystemEnvironment
    {
        #region _initialized
        private static bool _initialized;
        private static void CheckUnInit( )
        {
            if (_initialized) throw new NotSupportedException("MinGuiLuo.PluginSystem框架已经初始化完成！");
        }

        internal static void NotifyIntialized( )
        {
            _initialized = true;
        }
        #endregion

        #region 启动 Plugins
        /// <summary>
        /// 启动所有的 插件
        /// </summary>
        public static void StartupModulePlugins( )
        {
            CheckUnInit();

            foreach (var pluginAssembly in GetAllModules())
            {
                //调用 IModule
                var module = pluginAssembly.Instance as ModulePlugin;
                if (module != null) module.Initialize(LEnvironment.AppCore as IClientApp);
            }
        }
        #endregion

        #region  获取所有 Plugins
        private static IEnumerable<PluginAssembly> _modules;
       
        /// <summary>
        /// 找到当前程序所有可运行的 Module Dll
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<PluginAssembly> GetAllModules( )
        {
            if (_modules == null)
            {
                var files = EnumerateAllModuleFiles();
                _modules = LoadPlugins(files);
            }
            return _modules;
        }
        private static IEnumerable<string> EnumerateAllModuleFiles( )
        {
            yield return LEnvironment.MapDllPath("MinGuiLuo.dll");

            //查找 Module 目录下的所有程序集
            string modulePath = LEnvironment.MapDllPath("plugins\\");
            Directory.CreateDirectory(modulePath);
            foreach (var dll in Directory.GetFiles(modulePath, "*.dll"))
            {
                yield return dll;
            }
        }
        private static ReadOnlyCollection<PluginAssembly> LoadPlugins(IEnumerable<string> files)
        {
            return files.Select(file =>
            {
                var assembly = Assembly.LoadFrom(file);
                var pluginType = assembly.GetTypes().FirstOrDefault(t => typeof(IPlugin).IsAssignableFrom(t)
                    && !t.IsInterface && !t.IsAbstract);
                IPlugin pluginInstance = PluginAssembly.EmptyPlugin;

                if (pluginType != null)
                {
                    pluginInstance = Activator.CreateInstance(pluginType) as IPlugin;
                }

                return new PluginAssembly(assembly, pluginInstance);
            }).ToList().AsReadOnly();
        }
        #endregion
    }
}
